﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.Service.Data;
using System.Data.Common;
using System.Data;
using Sinacor.OMM.HFTMessageManager.ProcessEntity;

namespace Sinacor.OMM.HFTMessageManager.ResourceAccess
{
    public class HFTMessage
    {
        Sinacor.OMM.ConnectionManager.DataBase.DataBaseCommunicator _dataBaseCommunicator;
        public DbTransaction DbTransactionHFT = null;

        public HFTMessage(Sinacor.OMM.ConnectionManager.DataBase.DataBaseCommunicator dataBaseCommunicator)
        {
            _dataBaseCommunicator = dataBaseCommunicator;
        }

        public Sinacor.OMM.HFTMessageManager.ProcessEntity.OrderBalanceResponse RetrieveOrderBalance(Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.OrderParameter request)
        {
            string sql;
            Sinacor.OMM.HFTMessageManager.ProcessEntity.OrderBalanceResponse response = new Sinacor.OMM.HFTMessageManager.ProcessEntity.OrderBalanceResponse();
            sql = @"SELECT
                        MOV.QT_ORDEM - 
                        ( MOV.QT_ORDEXEC + MOV.QT_CANCOFE + NVL(
                            (SELECT SUM(D.QT_ORDEM) 
                                FROM 
                                    TORDETD D 
                                WHERE D.NR_SEQORD = MOV.NR_SEQORD 
                                AND D.NR_SUBSEQ = MOV.NR_SUBSEQ
                                AND D.DT_DATORD = MOV.DT_DATORD
                                AND D.NR_SEQDET NOT IN
                                (SELECT X.NR_SEQDET
                                    FROM TOREXEC X
                                    WHERE X.NR_SEQORD = MOV.NR_SEQORD
                                    AND X.NR_SUBSEQ = MOV.NR_SUBSEQ) ),0)) TOTALBALANCE,
                        MOV.NR_SEQORD ORDERSEQUENCIALNUMBER,
                        MOV.DT_DATORD ORDERDATE,
                        MOV.NR_SUBSEQ ORDERSUBSEQUENCIALNUMBER
                    FROM
                        TORMOVD MOV ,
                        TORDMEGA MEGA
                    WHERE   MOV.NR_SEQORD = MEGA.NR_SEQORD
                        AND MOV.Dt_Datord = MEGA.Dt_Datord
                        AND MOV.Nr_Subseq = MEGA.Nr_Subseq
                        AND MOV.CD_NATOPE = '" + request.OrderSide + @"'
                        AND MOV.CD_NEGOCIO = '" + request.TradeCode + @"'
                        AND MOV.CD_CLIENTE = " + request.Client + @"
                        AND MEGA.CD_OPERADOR = " + request.Operator + @"
                        AND MOV.Dt_Datord =  TO_DATE('" + request.SystemDate.ToString("dd/MM/yyyy") + @"','dd/MM/yyyy')";

            IDataReader reader = null;

            reader = _dataBaseCommunicator.ExecuteReader(sql);

            if (reader.Read())
            {
                response.Balance = reader.GetValue<Decimal>("TOTALBALANCE");
                response.OrderDate = reader.GetValue<DateTime>("ORDERDATE");
                response.OrderSequencialNumber = reader.GetValue<Int32>("ORDERSEQUENCIALNUMBER");
                response.OrderSubSequencialNumber = reader.GetValue<Int32>("ORDERSUBSEQUENCIALNUMBER");
            }
            reader.Close();
            reader.Dispose();
            reader = null;

            return response;

        }

        public bool CheckOrderExists(Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.OrderParameter request)
        {
            string sql;

            sql = @"SELECT 1
                        FROM
                            TORMOVD MOV 
                        INNER JOIN 
                            TORDMEGA MEGA ON ( 
                                MOV.NR_SEQORD = MEGA.NR_SEQORD AND 
                                MOV.Dt_Datord = MEGA.Dt_Datord AND 
                                MOV.Nr_Subseq = MEGA.Nr_Subseq)
                        WHERE
                            MOV.CD_NATOPE = '" + request.OrderSide + @"'
                            AND MOV.CD_NEGOCIO ='" + request.TradeCode + @"'
                            AND MOV.CD_CLIENTE = " + request.Client + @"
                            AND MEGA.CD_OPERADOR = " + request.Operator + @"
                            AND MOV.Dt_Datord = TO_DATE('" + request.SystemDate.ToString("dd/MM/yyyy") + @"','dd/MM/yyyy')";



            return (_dataBaseCommunicator.ExecuteScalar(sql) != null);

        }

        public void OrderAdditional(Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.OrderAdditionalParameter request)
        {

            string sql;

            sql = @" UPDATE 
                            TORMOVD 
                        SET 
                            QT_ORDEM = QT_ORDEM + " + request.AdditionalValue + @"
                        WHERE
                            NR_SEQORD = " + request.OrderSequencialNumber + @"
                            AND DT_DATORD = TO_DATE('" + request.OrderDate.ToString("dd/MM/yyyy") + @"','dd/MM/yyyy')
                            AND NR_SUBSEQ =" + request.OrderSubSequencialNumber;

            _dataBaseCommunicator.ExecuteNonQuery(DbTransactionHFT, sql);

        }

        public void IncludeMatchExecutionQueue(Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.MatchExecutionParameter request)
        {

            string sql;

            sql = @"INSERT INTO TORCASDET (
                            DT_DATORD, 
                            NR_SEQORD, 
                            NR_SUBSEQ, 
                            NR_SEQDET) 
                        VALUES (" +
                        "TO_DATE('" + request.OrderDate.ToString("dd/MM/yyyy") + "','dd/MM/yyyy')," +
                        request.OrderSequencialNumber + "," +
                        request.OrderSubSequencialNumber + "," +
                        request.sequencialCode + ")";

            _dataBaseCommunicator.ExecuteNonQuery(DbTransactionHFT, sql);

        }

        public int IncludeExecution(Sinacor.OMM.HFTMessageManager.ProcessEntity.ExecutionAttributes request)
        {

            int sequencialCode = 0;
            string sql;


            sequencialCode = RetrieveDetSequencial();
            string orderSide = request.OrderSide == Sinacor.OMM.MessageEntity.Enum.NaturezaOperacao.Compra ? "C" : "V";

            sql = @"INSERT INTO TORDETD (
                        NR_SEQDET,
                        IN_SITUAC,
                        DT_DATORD,
                        NR_SEQORD,
                        NR_SUBSEQ,
                        DT_HORORD,
                        DT_DATMOV,
                        TP_ORDEM,
                        CD_MERCAD,
                        QT_ORDEM,
                        VL_PREPAP,
                        CD_CONTRAPARTE,
                        IN_TOTAL,
                        TP_ESTRATEGIA,
                        NR_OFEMEGA,
                        CD_NEGOCIO_ESTR,
                        CD_NATOPE_ESTR,
                        CD_MSGORI_MEGA,
                        DT_SISTEMA  )
                    VALUES(" +
                        sequencialCode + "," +
                        "'M', " +
                        "TO_DATE('" + request.OrderDate.ToString("dd/MM/yyyy") + "','dd/MM/yyyy')," +
                        request.OrderSequencialNumber + "," +
                        request.OrderSubSequencialNumber + "," +
                        "TO_DATE('" + request.HourOrder.ToString("dd/MM/yyyy") + "','dd/MM/yyyy'), " +
                        "TO_DATE('" + request.SystemDate.ToString("dd/MM/yyyy") + "','dd/MM/yyyy')," +
                        request.OrderType + ",'" +
                        request.MarketCode + "'," +
                        request.Balance + "," +
                        request.Price + "," +
                        request.Counterparty + "," +
                        "'T', " +
                        "'N', " +
                        request.MegaOrder + ",'" +
                        request.Security + "','" +
                        orderSide + "'," +
                        request.FunctionCode + "," +
                        "PGE_GERAL.FGE_GETTMST())";


            _dataBaseCommunicator.ExecuteNonQuery(DbTransactionHFT, sql);

            return sequencialCode;
        }

        private int RetrieveDetSequencial()
        {
            string sql;
            int sequencialCode = 0;
            sql = "SELECT PR_OFMEGA.fOr_selTorseqdet() SEQUENCIALDET FROM DUAL";
            IDataReader reader = _dataBaseCommunicator.ExecuteReader(sql);
            if (reader.Read())
                sequencialCode = reader.GetValue<Int32>("SEQUENCIALDET");

            reader.Close();
            reader.Dispose();
            reader = null;

            return sequencialCode;
        }

        private void UpdateDetSequencial(int sequencial)
        {

            string sql;

            sql = @"UPDATE 
                        TORSEQDET 
                    SET 
                        NR_SEQDET = " + sequencial;
            _dataBaseCommunicator.ExecuteNonQuery(DbTransactionHFT, sql);
        }

        public ExecutionInformation RetrieveExecutionInformation(Sinacor.OMM.HFTMessageManager.ProcessEntity.Parameter.OrderAdditionalParameter request)
        {

            ExecutionInformation response = null;
            string sql;

            sql = @"SELECT 
                            DT_HORORD,
                            TP_ORDEM,
                            CD_MERCAD
                        FROM 
                            TORMOVD
                        WHERE
                            NR_SEQORD = " + request.OrderSequencialNumber + " AND " +
                        "DT_DATORD = TO_DATE('" + request.OrderDate.ToString("dd/MM/yyyy") + "','dd/MM/yyyy') AND " +
                        "NR_SUBSEQ =" + request.OrderSubSequencialNumber;

            IDataReader reader = _dataBaseCommunicator.ExecuteReader(sql);
            if (reader.Read())
            {
                response = new ExecutionInformation();
                response.HourOrder = reader.GetValue<DateTime>("DT_HORORD");
                response.MarketCode = reader.GetValue<String>("CD_MERCAD");
                response.OrderType = reader.GetValue<Int32>("TP_ORDEM");
            }
            reader.Close();
            reader.Dispose();
            reader = null;
            return response;
        }

        public void UpdateMessageIDProcessed(string strMsgId, string strMacAddress)
        {
            string sql;

            sql = @"UPDATE 
                        TBOPROS_IAFR
                    SET 
                        COD_ULT_MSG_PROS = '{0}'
                    WHERE
                        NUM_MAC_ETRB_PROS_IAFR = '{1}'";


            _dataBaseCommunicator.ExecuteNonQuery(DbTransactionHFT, string.Format(sql, strMsgId, strMacAddress));

        }

        public void UpdateMessageIDProcessed( string strMacAddress)
        {
            string sql;

            sql = @"UPDATE 
                        TBOPROS_IAFR
                    SET 
                        COD_ULT_MSG_PROS = Null
                    WHERE
                        NUM_MAC_ETRB_PROS_IAFR = '{0}'";


            _dataBaseCommunicator.ExecuteNonQuery(DbTransactionHFT, string.Format(sql, strMacAddress));

        }

    }
}
